using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using bitzhuwei.Compiler;

namespace bitzhuwei.AnsiCFormat {
    /// <summary>
    /// Correspond to the Vn node postfix_expression in the grammar(AnsiC).
    /// </summary>
    internal partial class Vnpostfix_expression : IFullFormatter {
        // [004]=postfix_expression : primary_expression ;
        // [005]=postfix_expression : postfix_expression '[' expression ']' ;
        // [006]=postfix_expression : postfix_expression '(' ')' ;
        // [007]=postfix_expression : postfix_expression '(' argument_expression_list ')' ;
        // [008]=postfix_expression : postfix_expression '.' 'identifier' ;
        // [009]=postfix_expression : postfix_expression '->' 'identifier' ;
        // [010]=postfix_expression : postfix_expression '++' ;
        // [011]=postfix_expression : postfix_expression '--' ;

        public readonly List<Item> list = new();

        private readonly TokenRange _scope;
        public TokenRange Scope => _scope;

        public void Format(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }

        public void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }

        public IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }
        // [4]=postfix_expression : primary_expression ;
        // dumped by ListExtractor 1
        internal Vnpostfix_expression(Vnprimary_expression first0) {

        }

        /// <summary>
        /// [005]=postfix_expression : postfix_expression '[' expression ']' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        public void Add(Token r2, Vnexpression r1, Token r0) {
            this.list.Add(new index_(r2, r1, r0));
        }
        /// <summary>
        /// [006]=postfix_expression : postfix_expression '(' ')' ;
        /// [007]=postfix_expression : postfix_expression '(' argument_expression_list ')' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        public void Add(Token r2, Vnargument_expression_list? r1, Token r0) {
            this.list.Add(new argList(r2, r1, r0));

        }
        /// <summary>
        /// [008]=postfix_expression : postfix_expression '.' 'identifier' ;
        /// [009]=postfix_expression : postfix_expression '->' 'identifier' ;
        /// </summary>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        public void Add(Token r1, Token r0) {
            this.list.Add(new refIdentifier(r1, r0));
        }
        /// <summary>
        /// [010]=postfix_expression : postfix_expression '++' ;
        /// [011]=postfix_expression : postfix_expression '--' ;
        /// </summary>
        /// <param name="r0"></param>
        public void Add(Token r0) {
            this.list.Add(new oneOperator(r0));
        }

        public abstract class Item { }

        public class index_ : Item {
            private readonly Token r2;
            private readonly Vnexpression r1;
            private readonly Token r0;

            // [005]=postfix_expression : postfix_expression '[' expression ']' ;
            public index_(Token r2, Vnexpression r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
            }

        }

        public class argList : Item {
            private readonly Token r2;
            private readonly Vnargument_expression_list? r1;
            private readonly Token r0;

            // [006]=postfix_expression : postfix_expression '(' ')' ;
            // [007]=postfix_expression : postfix_expression '(' argument_expression_list ')' ;
            public argList(Token r2, Vnargument_expression_list? r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
            }
        }

        public class refIdentifier : Item {
            // [008]=postfix_expression : postfix_expression '.' 'identifier' ;
            // [009]=postfix_expression : postfix_expression '->' 'identifier' ;

            private readonly Token op;
            private readonly Token identifier;
            public refIdentifier(Token r1, Token r0) {
                this.op = r1;
                this.identifier = r0;
            }
        }

        public class oneOperator : Item {
            // [010]=postfix_expression : postfix_expression '++' ;
            // [011]=postfix_expression : postfix_expression '--' ;

            private readonly Token op;
            public oneOperator(Token r0) {
                this.op = r0;
            }
        }

    }
}
